package com.example.demo.aspect;

import com.example.demo.annotation.DuplicateSubmitToken;
import com.example.demo.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * @Author: ak
 * @Date: 2020/4/8 17:21
 * @description 防止表单重复提交
 */
@Aspect
@Component
@Slf4j
public class DuplicateSubmitAspect {
    private static final String DUPLICATE_TOKEN_KEY = "duplicate_token_key";
    private static final String ERROR_MSG = "请不要重复提交表单";

    @Pointcut("execution(public * com.example.demo.controller..*(..))")
    public void webLog() {
    }

    @Around("webLog() && @annotation(token)")
    public Object around(ProceedingJoinPoint joinPoint, DuplicateSubmitToken token) {
        User user = (User)SecurityUtils.getSubject().getPrincipal();

        if (token != null) {
            Object[] args = joinPoint.getArgs();
            HttpServletRequest request = null;
            HttpServletResponse response = null;
            for (Object arg : args) {
                if (arg instanceof HttpServletRequest) {
                    request = (HttpServletRequest) arg;
                }
                if (arg instanceof HttpServletResponse) {
                    response = (HttpServletResponse) arg;
                }
            }
            if (request == null) {
                log.error("至少在DuplicateSubmitToken注解的方法上添加一个HttpServletRequest参数");
                return null;
            }
            boolean isSaveSession = token.save();
            if (isSaveSession) {
                Object t = request.getSession().getAttribute(DUPLICATE_TOKEN_KEY);
                if (null == t) {
                    try {
                        String uuid = UUID.randomUUID().toString();
                        request.getSession().setAttribute(DUPLICATE_TOKEN_KEY, uuid);
                        log.info("进入方法：token=" + uuid);
                        joinPoint.proceed();
                        log.info("方法完成，移除key");
                        request.getSession(false).removeAttribute(DUPLICATE_TOKEN_KEY);
                    } catch (Throwable throwable) {
                        throwable.printStackTrace();
                    }
                } else {
                    log.error(ERROR_MSG);
                    return null;
                }
            }
        }
        return null;
    }
}
